﻿using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace LabelPrintSystem
{
    public static class IniFile
    {//读写INI文件
        /// <summary>
        /// 地址
        /// </summary>
        public static string Path { get; private set; }

        #region API函数
        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);

        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string defVal, StringBuilder retVal, int size, string filePath);

        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string defVal, Byte[] retVal, int size, string filePath);
        #endregion

        /// <summary>
        /// 设置地址
        /// </summary>
        /// <param name="path"></param>
        internal static void SetFileName(string path)
        {//internal的类只能在同一个项目中使用
            Path = path;
        }

        /// <summary>
        /// 写
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="iValue"></param>
        public static void IniWriteValue(string section, string key, string iValue)
        {
            WritePrivateProfileString(section, key, iValue, Path);
        }

        /// <summary>
        /// 读
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="defval"></param>
        /// <returns></returns>
        public static string IniReadValue(string section, string key, string defval)
        {
            StringBuilder temp = new StringBuilder(255);
            int i = GetPrivateProfileString(section, key, defval, temp, 255, Path);
            return temp.ToString();
        }
    }

    public class XmlUtil
    {//XML
        public XmlUtil() { }

        #region XML Serialization

        public static string ToXml(Object objToXml, bool includeNameSpace, bool omit)
        {
            XmlWriter stWriter = null;//XML编写器
            XmlSerializer xmlSerializer;//XML序列化/反序列化对象
            string buffer;
            try
            {
                xmlSerializer = new XmlSerializer(objToXml.GetType());//序列化实例，代入类型

                StringBuilder sb = new StringBuilder();
                /* XmlWriter 表示一个编写器，该编写器提供一种快速、非缓存和只进的方式来生成包含 XML 数据的流或文件。
                *  XmlWriter.Create() 使用 System.Text.StringBuilder 和 System.Xml.XmlWriterSettings 对象创建一个新的 System.Xml.XmlWriter
                *   OmitXmlDeclaration = true   获取或设置一个值，该值指示是否编写 XML 声明。
                */
                stWriter = XmlWriter.Create(sb, new XmlWriterSettings() { OmitXmlDeclaration = omit });

                if (!includeNameSpace)
                {
                    System.Xml.Serialization.XmlSerializerNamespaces xs = new XmlSerializerNamespaces();//包含 System.Xml.Serialization.XmlSerializer 用于在 XML 文档实例中生成限定名的 XML 命名空间和前缀。
                    xs.Add("", "");//To remove namespace and any other inline information tag
                    xmlSerializer.Serialize(stWriter, objToXml, xs); //使用指定的 System.Xml.XmlWriter 和指定命名空间序列化指定的 System.Object 并将 XML 文档写入文件。
                }
                else
                {
                    xmlSerializer.Serialize(stWriter, objToXml);//使用指定的 System.Xml.XmlWriter 序列化指定的 System.Object 并将 XML 文档写入文件
                }
                buffer = sb.ToString();
            }
            catch (Exception Ex)
            {
                throw Ex;
            }
            finally
            {
                if (stWriter != null) stWriter.Close();//关闭此流和基础流
            }
            return buffer;
        }

        /// <summary>
        /// Converts an object to an xml string.
        /// </summary>
        /// <param name="objToXml">Object wanted to be converted to xml string</param>
        /// <returns>Xml string of the object</returns>		
        public static string ToXml(Object objToXml, bool includeNameSpace)
        {
            StreamWriter stWriter = null;
            XmlSerializer xmlSerializer;
            string buffer;
            try
            {
                xmlSerializer = new XmlSerializer(objToXml.GetType());
                MemoryStream memStream = new MemoryStream();
                stWriter = new StreamWriter(memStream);
                if (!includeNameSpace)
                {
                    System.Xml.Serialization.XmlSerializerNamespaces xs = new XmlSerializerNamespaces();
                    xs.Add("", "");//To remove namespace and any other inline information tag
                    xmlSerializer.Serialize(stWriter, objToXml, xs);
                }
                else
                {
                    xmlSerializer.Serialize(stWriter, objToXml);
                }
                buffer = Encoding.ASCII.GetString(memStream.GetBuffer());
            }
            catch (Exception Ex)
            {
                throw Ex;
            }
            finally
            {
                if (stWriter != null) stWriter.Close();
            }
            return buffer;
        }

        /// <summary>
        /// Serializes a given object to the file given with the path
        /// </summary>
        /// <param name="objToXml">Object wanted to be serialized to the file</param>
        /// <param name="filePath">Path of the file</param>		
        public static void ToXml(Object objToXml, string filePath, bool includeNameSpace)
        {
            StreamWriter stWriter = null;
            XmlSerializer xmlSerializer;
            try
            {
                xmlSerializer = new XmlSerializer(objToXml.GetType());
                stWriter = new StreamWriter(filePath);
                if (!includeNameSpace)
                {
                    System.Xml.Serialization.XmlSerializerNamespaces xs = new XmlSerializerNamespaces();
                    xs.Add("", "");//To remove namespace and any other inline information tag
                    xmlSerializer.Serialize(stWriter, objToXml, xs);
                }
                else
                {
                    xmlSerializer.Serialize(stWriter, objToXml);
                }
            }
            catch (Exception exception)
            {
                throw exception;
            }
            finally
            {
                if (stWriter != null) stWriter.Close();
            }
        }

        /// <summary>
        /// Serializes a given object to the file given with the path
        /// </summary>
        /// <param name="objToXml">Object wanted to be serialized to the file</param>
        /// <param name="includeStartDocument">Includes the <?xml version="1.0" encoding="utf-8" ?> line if it is true, otherwise start doucment line is excluded from the exported xml.</param>
        /// <param name="filePath">Path of the file</param>		
        public static void ToXml(Object objToXml, string filePath, bool includeNameSpace, bool includeStartDocument)
        {
            SpecialXmlWriter stWriter = null;
            XmlSerializer xmlSerializer;
            try
            {
                xmlSerializer = new XmlSerializer(objToXml.GetType());
                stWriter = new SpecialXmlWriter(filePath, null, includeStartDocument);
                System.Xml.Serialization.XmlSerializerNamespaces xs = new XmlSerializerNamespaces();
                xs.Add("", "");//To remove namespace and any other inline information tag
                xmlSerializer.Serialize(stWriter, objToXml, xs);
            }
            catch (Exception Ex)
            {
                throw Ex;
            }
            finally
            {
                if (stWriter != null) stWriter.Close();
            }
        }

        /// <summary>
        /// Deserializes the object given with the type from the given string
        /// </summary>
        /// <param name="xmlString">String containing the serialized xml form of the object</param>
        /// <param name="type">Type of the object to be deserialized</param>
        /// <returns>Deserialized object</returns>
        public static object XmlTo(string xmlString, Type type)
        {//XML反序列化，代入XML字符串，及需要转换的类型
            XmlSerializer xmlSerializer;//声明XML序列
            MemoryStream memStream = null;//创建一个流，其后备存储为内存
            try
            {
                xmlSerializer = new XmlSerializer(type);//指定类型XML实例
                byte[] bytes = new byte[xmlString.Length];//声明与XML字符串大小相同的字节数据
                Encoding.ASCII.GetBytes(xmlString, 0, xmlString.Length, bytes, 0);//将指定 System.String 中的一组字符编码到指定的字节数组中
                memStream = new MemoryStream(bytes);//基于指定的字节数组初始化 MemoryStream 类的无法调整大小的新实例
                object objectFromXml = xmlSerializer.Deserialize(memStream);//反序列化
                return objectFromXml;
            }
            catch (Exception Ex)
            {
                throw Ex;
            }
            finally
            {
                if (memStream != null) memStream.Close();//关闭当前流并释放与之关联的所有资源（如套接字和文件句柄）
            }
        }
        public static object XmlToDeserialize(string xml, Type type)
        {
            try
            {
                using (StringReader sr = new StringReader(xml))
                {
                    XmlSerializer xmldes = new XmlSerializer(type);
                    return xmldes.Deserialize(sr);
                }
            }
            catch (Exception e)
            {
                return null;
            }
        }

        /// <summary>
        /// Deserializes the object given with the type from the given string
        /// </summary>
        /// <param name="xmlString">String containing the serialized xml form of the object</param>
        /// <param name="type">Type of the object to be deserialized</param>
        /// <returns>Deserialized object</returns>
        public static object XmlToFromFile(string filePath, Type type)
        {
            XmlSerializer xmlSerializer;
            FileStream fileStream = null;
            try
            {
                xmlSerializer = new XmlSerializer(type);
                fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                object objectFromXml = xmlSerializer.Deserialize(fileStream);
                return objectFromXml;
            }
            catch (Exception Ex)
            {
                throw Ex;
            }
            finally
            {
                if (fileStream != null) fileStream.Close();
            }
        }

        public static string FormatXml(string source)
        {//xml格式
            var sb = new StringBuilder();
            XmlTextWriter writer = null;
            try
            {
                var doc = new XmlDocument();
                doc.LoadXml(source);//从指定的字符串加载 XML 文档。
                writer = new XmlTextWriter(new StringWriter(sb))
                {
                    Formatting = Formatting.Indented//xml自动缩进
                };
                doc.WriteTo(writer); //将 XmlDocument 节点保存到指定的 System.Xml.XmlWriter。
            }
            finally
            {
                if (writer != null) writer.Close();//关闭此流和基础流。
            }

            return sb.ToString();
        }

        public static string FormatInnerXml(string source)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(source);
            if (doc.DocumentElement != null)
            {
                return doc.DocumentElement.InnerXml;
            }

            return source;
        }

        #endregion XML Serialization

        #region SOAP Serialization

        /// <summary>
        /// DeSerializes a string into a  object 
        /// </summary>
        /// <param name="strFieldObject">String to be deserialized</param>
        /// <returns>Deserialized field object</returns>
        public static object SoapTo(string soapString)
        {
            IFormatter formatter;
            MemoryStream memStream = null;
            Object objectFromSoap = null;
            try
            {
                byte[] bytes = new byte[soapString.Length];
                Encoding.ASCII.GetBytes(soapString, 0, soapString.Length, bytes, 0);
                memStream = new MemoryStream(bytes);
                formatter = new SoapFormatter();
                objectFromSoap = formatter.Deserialize(memStream);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            finally
            {
                if (memStream != null) memStream.Close();
            }
            return objectFromSoap;
        }

        /// <summary>
        /// DeSerializes a string into a  object 
        /// </summary>
        /// <param name="strFieldObject">String to be deserialized</param>
        /// <returns>Deserialized field object</returns>
        public static object SoapToFromFile(string filePath)
        {
            IFormatter formatter;
            FileStream fileStream = null;
            Object objectFromSoap = null;
            try
            {
                fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                formatter = new SoapFormatter();
                objectFromSoap = formatter.Deserialize(fileStream);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            finally
            {
                if (fileStream != null) fileStream.Close();
            }
            return objectFromSoap;
        }

        /// <summary>
        /// Serializes the field object into a string
        /// </summary>
        /// <param name="objField">Field Object to be serialized</param>
        /// <returns>Serialized field object</returns>
        public static string ToSoap(Object objToSoap)
        {
            IFormatter formatter;
            MemoryStream memStream = null;
            string strObject = "";
            try
            {
                memStream = new MemoryStream();
                formatter = new SoapFormatter();
                formatter.Serialize(memStream, objToSoap);
                strObject = Encoding.ASCII.GetString(memStream.GetBuffer());
                int index = strObject.IndexOf("\0");//Check for the null terminator character
                if (index > 0)
                {
                    strObject = strObject.Substring(0, index);
                }
            }
            catch (Exception exception)
            {
                throw exception;
            }
            finally
            {
                if (memStream != null) memStream.Close();
            }
            return strObject;
        }

        /// <summary>
        /// Serializes the field object into a string
        /// </summary>
        /// <param name="objField">Field Object to be serialized</param>
        /// <returns>Serialized field object</returns>
        public static void ToSoap(Object objToSoap, string filePath)
        {
            IFormatter formatter;
            FileStream fileStream = null;
            try
            {
                fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write);
                formatter = new SoapFormatter();
                formatter.Serialize(fileStream, objToSoap);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            finally
            {
                if (fileStream != null) fileStream.Close();
            }
        }

        /// <summary>
        /// DeSerializes a string into a  object 
        /// </summary>
        /// <param name="strFieldObject">String to be deserialized</param>
        /// <returns>Deserialized field object</returns>
        public static object SoapToFromFile(string filePath, SerializationBinder binder)
        {
            IFormatter formatter;
            FileStream fileStream = null;
            Object objectFromSoap = null;
            try
            {
                fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                formatter = new SoapFormatter();
                formatter.Binder = binder;
                objectFromSoap = formatter.Deserialize(fileStream);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            finally
            {
                if (fileStream != null) fileStream.Close();
            }
            return objectFromSoap;
        }

        #endregion XML Serialization
    }

    #region SpecialXmlWriter

    public class SpecialXmlWriter : XmlTextWriter
    {
        bool m_includeStartDocument = true;
        public SpecialXmlWriter(TextWriter tw, bool includeStartDocument)
            : base(tw)
        {
            m_includeStartDocument = includeStartDocument;
        }
        public SpecialXmlWriter(Stream sw, Encoding encoding, bool includeStartDocument)
            : base(sw, null)
        {
            m_includeStartDocument = includeStartDocument;
        }
        public SpecialXmlWriter(string filePath, Encoding encoding, bool includeStartDocument)
            : base(filePath, null)
        {
            m_includeStartDocument = includeStartDocument;
        }
        public override void WriteStartDocument()
        {
            if (m_includeStartDocument)
            {
                base.WriteStartDocument();
            }
        }
    }

    #endregion SpecialXmlWriter
}
